package com.och.mrcp.service.impl;

import com.alibaba.nls.client.protocol.NlsClient;
import com.alibaba.nls.client.protocol.OutputFormatEnum;
import com.alibaba.nls.client.protocol.SampleRateEnum;
import com.alibaba.nls.client.protocol.tts.SpeechSynthesizer;
import com.alibaba.nls.client.protocol.tts.SpeechSynthesizerListener;
import com.alibaba.nls.client.protocol.tts.SpeechSynthesizerResponse;
import com.och.mrcp.config.EngineConfig;
import com.och.mrcp.core.rtp.session.RtpSession;
import com.och.mrcp.model.SynthesisResult;
import com.och.mrcp.util.AudioConverter;
import lombok.extern.slf4j.Slf4j;

import javax.sound.sampled.AudioFormat;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 阿里云TTS语音合成会话
 * 基于阿里云官方SDK实现的流式语音合成
 */
@Slf4j
public class AliyunTtsSession {
    
    private final String sessionId;
    private final String appKey;
    private final NlsClient nlsClient;
    private final EngineConfig.SynthesisConfig config;
    private final RtpSession rtpSession;
    private final CompletableFuture<SynthesisResult> resultFuture;
    
    private SpeechSynthesizer synthesizer;
    private final AtomicBoolean isStarted = new AtomicBoolean(false);
    private final AtomicBoolean isCompleted = new AtomicBoolean(false);
    private final AtomicLong startTime = new AtomicLong(0);
    
    // 用于收集音频数据
    private final ByteArrayOutputStream audioBuffer = new ByteArrayOutputStream();
    private boolean firstPacketReceived = false;
    
    public AliyunTtsSession(String sessionId, String appKey, NlsClient nlsClient, 
                           EngineConfig.SynthesisConfig config, RtpSession rtpSession) {
        this.sessionId = sessionId;
        this.appKey = appKey;
        this.nlsClient = nlsClient;
        this.config = config;
        this.rtpSession = rtpSession;
        this.resultFuture = new CompletableFuture<>();
        
        log.info("AliyunTtsSession created for session: {}", sessionId);
    }
    
    /**
     * 开始语音合成
     */
    public CompletableFuture<SynthesisResult> startSynthesis(String text) {
        if (!isStarted.compareAndSet(false, true)) {
            return CompletableFuture.failedFuture(new IllegalStateException("Session already started"));
        }
        
        try {
            log.info("Starting TTS synthesis for session: {}, text: '{}'", sessionId, text);
            
            // 创建合成器
            synthesizer = new SpeechSynthesizer(nlsClient, createSynthesizerListener());
            
            // 配置合成器
            configureSynthesizer(text);
            
            // 开始合成
            startTime.set(System.currentTimeMillis());
            synthesizer.start();
            
            log.info("TTS synthesis started for session: {}", sessionId);
            
        } catch (Exception e) {
            log.error("Failed to start TTS synthesis for session: {}", sessionId, e);
            resultFuture.completeExceptionally(e);
        }
        
        return resultFuture;
    }
    
    /**
     * 停止语音合成
     */
    public void stopSynthesis() {
        if (synthesizer != null && !isCompleted.get()) {
            try {
                synthesizer.close();
                log.info("TTS synthesis stopped for session: {}", sessionId);
            } catch (Exception e) {
                log.error("Error stopping TTS synthesis for session: {}", sessionId, e);
            }
        }
    }
    
    /**
     * 清理资源
     */
    public void cleanup() {
        stopSynthesis();
        try {
            audioBuffer.close();
        } catch (IOException e) {
            log.warn("Error closing audio buffer for session: {}", sessionId, e);
        }
    }
    
    /**
     * 获取合成结果Future
     */
    public CompletableFuture<SynthesisResult> getResultFuture() {
        return resultFuture;
    }
    
    /**
     * 配置语音合成器
     */
    private void configureSynthesizer(String text) {
        // 设置AppKey
        synthesizer.setAppKey(appKey);
        
        // 设置音频格式
        OutputFormatEnum format = mapOutputFormat(config.getFormat());
        synthesizer.setFormat(format);
        
        // 设置采样率
        SampleRateEnum sampleRate = mapSampleRate(config.getSampleRate());
        synthesizer.setSampleRate(sampleRate);
        
        // 设置发音人
        String voice = config.getVoice();
        if (voice != null && !voice.isEmpty()) {
            synthesizer.setVoice(voice);
        } else {
            synthesizer.setVoice("xiaoyun"); // 默认发音人
        }
        
        // 设置语速（范围：-500~500）
        int speechRate = Math.max(-500, Math.min(500, config.getSpeed()));
        synthesizer.setSpeechRate(speechRate);
        
        // 设置音调（范围：-500~500）
        int pitchRate = Math.max(-500, Math.min(500, config.getPitch()));
        synthesizer.setPitchRate(pitchRate);
        
        // 设置合成文本
        synthesizer.setText(text);
        
        // 启用字幕功能（可选）
        synthesizer.addCustomedParam("enable_subtitle", false);
        
        log.debug("TTS synthesizer configured for session: {}, voice: {}, format: {}, sampleRate: {}, speechRate: {}, pitchRate: {}", 
                sessionId, voice, format, sampleRate, speechRate, pitchRate);
    }
    
    /**
     * 映射输出格式
     */
    private OutputFormatEnum mapOutputFormat(String format) {
        if (format == null) return OutputFormatEnum.PCM;
        
        switch (format.toLowerCase()) {
            case "wav":
                return OutputFormatEnum.WAV;
            case "mp3":
                return OutputFormatEnum.MP3;
            case "pcm":
            default:
                return OutputFormatEnum.PCM;
        }
    }
    
    /**
     * 映射采样率
     */
    private SampleRateEnum mapSampleRate(int sampleRate) {
        switch (sampleRate) {
            case 16000:
                return SampleRateEnum.SAMPLE_RATE_16K;
            case 8000:
                return SampleRateEnum.SAMPLE_RATE_8K;
            case 24000:
                return SampleRateEnum.SAMPLE_RATE_24K;
            default:
                log.warn("Unsupported sample rate: {}, using 16K", sampleRate);
                return SampleRateEnum.SAMPLE_RATE_16K;
        }
    }
    
    /**
     * 创建语音合成监听器
     */
    private SpeechSynthesizerListener createSynthesizerListener() {
        return new SpeechSynthesizerListener() {
            
            @Override
            public void onComplete(SpeechSynthesizerResponse response) {
                if (isCompleted.compareAndSet(false, true)) {
                    long duration = System.currentTimeMillis() - startTime.get();
                    
                    log.info("TTS synthesis completed for session: {}, status: {}, duration: {}ms", 
                            sessionId, response.getStatus(), duration);
                    
                    // 创建合成结果
                    SynthesisResult result = new SynthesisResult();
                    result.setAudioData(audioBuffer.toByteArray());
                    result.setFormat(config.getFormat());
                    result.setSampleRate(config.getSampleRate());
                    result.setChannels(config.getChannels());
                    result.setDuration(duration);
                    result.setText(response.getName()); // 使用响应中的文本
                    
                    // 完成Future
                    resultFuture.complete(result);
                    
                    log.debug("TTS result created for session: {}, audio size: {} bytes", 
                            sessionId, result.getAudioData().length);
                }
            }
            
            @Override
            public void onMessage(ByteBuffer message) {
                try {
                    if (!firstPacketReceived) {
                        firstPacketReceived = true;
                        long firstPacketLatency = System.currentTimeMillis() - startTime.get();
                        log.info("TTS first packet received for session: {}, latency: {}ms", 
                                sessionId, firstPacketLatency);
                    }
                    
                    // 将音频数据写入缓冲区
                    byte[] audioData = new byte[message.remaining()];
                    message.get(audioData);
                    audioBuffer.write(audioData);
                    
                    // 通过RTP发送音频数据（如果RTP会话可用）
                    if (rtpSession != null) {
                        sendAudioToRtp(audioData);
                    }
                    
                    log.debug("TTS audio packet received for session: {}, size: {} bytes", 
                            sessionId, audioData.length);
                    
                } catch (Exception e) {
                    log.error("Error processing TTS audio message for session: {}", sessionId, e);
                }
            }
            
            @Override
            public void onFail(SpeechSynthesizerResponse response) {
                if (isCompleted.compareAndSet(false, true)) {
                    String error = String.format("TTS synthesis failed for session: %s, task_id: %s, status: %s, status_text: %s", 
                            sessionId, response.getTaskId(), response.getStatus(), response.getStatusText());
                    
                    log.error(error);
                    resultFuture.completeExceptionally(new RuntimeException(error));
                }
            }
        };
    }
    
    /**
     * 通过RTP发送音频数据
     */
    private void sendAudioToRtp(byte[] audioData) {
        try {
            if (rtpSession != null) {
                // 检查是否需要音频格式转换
                byte[] convertedAudio = convertAudioForRtp(audioData);
                
                // 使用RtpSession的sendAudioData方法发送音频
                rtpSession.sendAudioData(convertedAudio);
                log.debug("Audio data sent to RTP for session: {}, original size: {} bytes, converted size: {} bytes", 
                        sessionId, audioData.length, convertedAudio.length);
            } else {
                log.warn("RTP session is null, cannot send audio data for session: {}", sessionId);
            }
            
        } catch (Exception e) {
            log.error("Error sending audio to RTP for session: {}", sessionId, e);
        }
    }
    
    /**
     * 为RTP传输转换音频格式
     */
    private byte[] convertAudioForRtp(byte[] audioData) {
        try {
            // 创建阿里云TTS输出格式（基于配置）
            AudioFormat sourceFormat = createSourceAudioFormat();
            
            // 创建RTP标准格式（通常是8kHz或16kHz PCM）
            AudioFormat targetFormat = AudioConverter.createRtpAudioFormat(
                    config.getSampleRate(), 
                    config.getChannels()
            );
            
            // 如果格式不同，进行转换
            if (!isFormatCompatible(sourceFormat, targetFormat)) {
                log.debug("Converting audio format for RTP: {} -> {}", 
                        formatToString(sourceFormat), formatToString(targetFormat));
                
                return AudioConverter.convertAudio(audioData, sourceFormat, targetFormat);
            }
            
            return audioData;
            
        } catch (Exception e) {
            log.warn("Audio format conversion failed, using original data: {}", e.getMessage());
            return audioData;
        }
    }
    
    /**
     * 创建源音频格式（阿里云TTS输出）
     */
    private AudioFormat createSourceAudioFormat() {
        // 根据配置创建音频格式
        AudioFormat.Encoding encoding = AudioFormat.Encoding.PCM_SIGNED;
        
        // 阿里云TTS通常输出16位PCM
        int sampleSizeInBits = 16;
        boolean bigEndian = false;
        
        return new AudioFormat(
                encoding,
                config.getSampleRate(),
                sampleSizeInBits,
                config.getChannels(),
                config.getChannels() * (sampleSizeInBits / 8),
                config.getSampleRate(),
                bigEndian
        );
    }
    
    /**
     * 检查两个格式是否兼容
     */
    private boolean isFormatCompatible(AudioFormat format1, AudioFormat format2) {
        return format1.getEncoding().equals(format2.getEncoding()) &&
               Math.abs(format1.getSampleRate() - format2.getSampleRate()) < 0.1 &&
               format1.getSampleSizeInBits() == format2.getSampleSizeInBits() &&
               format1.getChannels() == format2.getChannels();
    }
    
    /**
     * 格式转换为字符串
     */
    private String formatToString(AudioFormat format) {
        return String.format("%s, %.1fHz, %d-bit, %d channels",
                format.getEncoding(),
                format.getSampleRate(),
                format.getSampleSizeInBits(),
                format.getChannels());
    }
    
    /**
     * 获取会话ID
     */
    public String getSessionId() {
        return sessionId;
    }
    
    /**
     * 检查会话是否已启动
     */
    public boolean isStarted() {
        return isStarted.get();
    }
    
    /**
     * 检查会话是否已完成
     */
    public boolean isCompleted() {
        return isCompleted.get();
    }
}
